#pragma once



#include <time.h>
#include <Winsock2.h>
#include <stdlib.h>


#include "../qarray.h"
using namespace micro::utils;


namespace micro
{
namespace net
{

#ifdef NOLFS
#define off64_t long
#else
#define off64_t size_t
#endif
	 

typedef int ( *FtpCallbackXfer )( off64_t xfered, void* arg );
typedef int ( *FtpCallbackIdle )( void* arg );
typedef void ( *FtpCallbackLog )( char* str, void* arg, bool out );


struct ftphandle
{
    char*			cput;
    char*			cget;
    int				handle;
    int				cavail, cleft;
    char*			buf;
    int				dir;
    ftphandle*		ctrl;
    int				cmode;
    timeval			idletime;

    FtpCallbackXfer xfercb;
    FtpCallbackIdle idlecb;
    FtpCallbackLog	logcb;

    void*			cbarg;
    off64_t			xfered;
    off64_t			cbbytes;
    off64_t			xfered1;
    char			response[256];


    off64_t offset;
    bool correctpasv;
};


class QFtpLite
{

    enum accesstype
    {
        dir = 1,
        dirverbose,
        fileread,
        filewrite,
        filereadappend,
        filewriteappend
    };

    enum transfermode
    {
        ascii = 'A',
        image = 'I'
    };

    enum connmode
    {
        pasv = 1,
        port
    };

    enum fxpmethod
    {
        defaultfxp = 0,
        alternativefxp
    };

    enum dataencryption
    {
        unencrypted = 0,
        secure
    };

private:
	ftphandle* mp_ftphandle;


public:
    QFtpLite();
    ~QFtpLite();


    int Connect( const char* host );
    int Login( const char* user, const char* pass );


	int Dir( QBuffer & buffer, const char* path );


public:
    int Site( const char* cmd );
    int Raw( const char* cmd );
    int SysType( char* buf, int max );
    int Mkdir( const char* path );
    int Chdir( const char* path );
    int Cdup();
    int Rmdir( const char* path );
    int Pwd( char* path, int max );
    int Nlst( const char* outputfile, const char* path );
    int Dir( const char* outputfile, const char* path );
    int QSize( const char* path, int* size, transfermode mode );

    int ModDate( const char* path, char* dt, int max );
    int Get( const char* outputfile, const char* path, transfermode mode, off64_t offset = 0 );
    int Put( const char* inputfile, const char* path, transfermode mode, off64_t offset = 0 );
    int Rename( const char* src, const char* dst );
    int Delete( const char* path );
    
	int Quit();
    char* LastResponse();


    void SetCallbackIdleFunction( FtpCallbackIdle pointer );
    void SetCallbackLogFunction( FtpCallbackLog pointer );
    void SetCallbackXferFunction( FtpCallbackXfer pointer );
    void SetCallbackArg( void* arg );
    void SetCallbackBytes( off64_t bytes );
    void SetCorrectPasv( bool b )
    {
        mp_ftphandle->correctpasv = b;
    };
    void SetCallbackIdletime( int time );
    void SetConnmode( connmode mode );
    static int Fxp( QFtpLite* src, QFtpLite* dst, const char* pathSrc, const char* pathDst, transfermode mode, fxpmethod method );

    ftphandle* RawOpen( const char* path, accesstype type, transfermode mode );
    int RawClose( ftphandle* handle );
    int RawWrite( void* buf, int len, ftphandle* handle );
    int RawRead( void* buf, int max, ftphandle* handle );


private:
	int FtpXferBuffer( QBuffer& buffer, const char * path, ftphandle * nControl, accesstype type, transfermode mode );


private:
    int FtpXfer( const char* localfile, const char* path, ftphandle* nControl, accesstype type, transfermode mode );
    int FtpOpenPasv( ftphandle* nControl, ftphandle** nData, transfermode mode, int dir, char* cmd );
    int FtpSendCmd( const char* cmd, char expresp, ftphandle* nControl );
    int FtpAcceptConnection( ftphandle* nData, ftphandle* nControl );
    int FtpOpenPort( ftphandle* nControl, ftphandle** nData, transfermode mode, int dir, char* cmd );
    int FtpRead( void* buf, int max, ftphandle* nData );
    int FtpWrite( void* buf, int len, ftphandle* nData );
    int FtpAccess( const char* path, accesstype type, transfermode mode, ftphandle* nControl, ftphandle** nData );
    int FtpClose( ftphandle* nData );

    int socket_wait( ftphandle* ctl );
    int readline( char* buf, int max, ftphandle* ctl );
    int writeline( char* buf, int len, ftphandle* nData );
    int readresp( char c, ftphandle* nControl );

    void ClearHandle();
    int CorrectPasvResponse( unsigned int * v );
};





}//namespace

}//micro